package com.ksxy.afingerprint.core

import android.os.Build
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import android.support.annotation.RequiresApi
import java.security.Key
import java.security.KeyStore
import java.security.KeyStoreException
import java.security.SecureRandom
import java.util.*
import javax.crypto.Cipher
import javax.crypto.KeyGenerator

/**
 *  author : chenyinying
 *  e-mail : me@korion.cn
 *  time   : 2018/07/07
 *  desc   :
 *  version: 1.0
 */
object KeyStoreHelper {

    private const val KEY_STORE_TYPE = "AndroidKeyStore"
    private var inited = false
    private val mKeyStore = KeyStore.getInstance(KEY_STORE_TYPE)

    fun init(){
        try {
            mKeyStore.load(null)
            inited = true
        }catch (e: Exception){
            e.printStackTrace()
        }finally {
            if(!inited)
                throw RuntimeException("Error: KeyStore init fail")
        }
    }

    @RequiresApi(Build.VERSION_CODES.M)
    fun createSecretKey(keyAlias: String): Boolean{
        hasInited()
        val keyGen = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEY_STORE_TYPE)
        val keyGenParamsBuilder = KeyGenParameterSpec.Builder(
                keyAlias,
                KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .setUserAuthenticationRequired(true)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            keyGenParamsBuilder.setInvalidatedByBiometricEnrollment(false)
        }

        keyGen.init(keyGenParamsBuilder.build(),
                SecureRandom("1024".toByteArray(Charsets.UTF_8)))
        keyGen.generateKey()
        return true
    }

    fun deleteKey(keyAlias: String?): Boolean{
        hasInited()
        try {
            mKeyStore.deleteEntry(keyAlias)
            return true
        }catch (e: KeyStoreException){
            e.printStackTrace()
            return false
        }
    }

    fun getKeyByAlais(keyAlias: String?): Key?{
        hasInited()
        if (keyAlias == null){
            return null
        }
        return mKeyStore.getKey(keyAlias, null)
    }

    fun isExistedKey(keyAlias: String?): Boolean{
        hasInited()
        if (keyAlias == null){
            return false
        }
        return mKeyStore.containsAlias(keyAlias)
    }

    fun getAllKeys(): Enumeration<String>? {
        hasInited()
        return mKeyStore.aliases()
    }

    private fun hasInited(){
        if(!inited){
            throw IllegalAccessException("Please invoke init() before")
        }
    }
}

